import uix
import uiconst
import util
import planetCommon
import math
import uicls
import planet
import draw
import blue
import uthread
import const
import uiutil
import listentry
import geo2
from PlanetResources import builder
import random

class SurveyWindow(uicls.Window):
    __guid__ = 'form.PlanetSurvey'
    __notifyevents__ = ['OnPlanetViewChanged',
     'OnEditModeChanged',
     'OnEditModeBuiltOrDestroyed']
    default_fixedWidth = 700
    default_fixedHeight = 256

    def ApplyAttributes(self, attributes):
        uicls.Window.ApplyAttributes(self, attributes)
        self.ecuPinID = attributes.get('ecuPinID')
        self.barGraphUpdating = False
        self.planetUISvc = sm.GetService('planetUI')
        self.planet = self.planetUISvc.planet
        self.pin = self.planet.GetPin(self.ecuPinID)
        self.extractionHeadValues = {}
        self.resourceTypeIDs = self.planet.remoteHandler.GetPlanetResourceInfo().keys()
        self.currResourceTypeID = self.pin.programType
        self.outputVals = []
        self.programCycleTime = None
        self.dragThread = None
        self.flashStateColorThread = None
        self.currCycleTime = None
        self.sh = None
        if (self.currResourceTypeID is not None):
            (inRange, self.sh,) = self.planetUISvc.planet.GetResourceData(self.currResourceTypeID)
        self.revertToResource = self.planetUISvc.selectedResourceTypeID
        self.currentResource = None
        self.editsEnabled = ((self.pin.GetExtractionType() is None) or (self.pin.GetTimeToExpiry() <= 0))
        if self.editsEnabled:
            self.planetUISvc.myPinManager.UnlockHeads(self.pin.id)
        self.barTimeIndicatorThread = None
        self.overlapValues = {}
        self.stateColor = None
        self.pinData = None
        if self.pin.IsInEditMode():
            self.pinData = self.pin.Serialize()
        self.SetTopparentHeight(10)
        self.MakeUnResizeable()
        captionTxt = (mls.UI_PI_SURVEYINGPROGRAM % {'pinName': planetCommon.GetGenericPinName(self.pin.typeID, self.pin.id)})
        self.SetCaption(captionTxt)
        self.bottomCont = uicls.Container(name='bottomCont', parent=self.sr.main, align=uiconst.TOBOTTOM, height=30)
        self.leftCont = uicls.Container(name='leftCont', parent=self.sr.main, align=uiconst.TOLEFT, width=130, padding=(6, 0, 3, 0))
        self.rightCont = uicls.Container(name='rightCont', parent=self.sr.main, align=uiconst.TORIGHT, width=145, padding=(10, 5, 5, 5))
        self.centerCont = uicls.Container(name='centerCont', parent=self.sr.main, align=uiconst.TOALL, padTop=3)
        self._ConstructLeftContainer()
        self._ConstructCenterContainer()
        self._ConstructRightContainer()
        self._ConstructBottomContainer()



    def _ConstructLeftContainer(self):
        textCont = uicls.Container(parent=self.leftCont, height=15, align=uiconst.TOTOP)
        planet.ui.CaptionLabel(parent=textCont, text=mls.UI_PI_EXTRACTORHEADUNITS, align=uiconst.TOTOP)
        self.headButtons = []
        headEntryCont = uicls.Container(parent=self.leftCont, name='headEntryCont', align=uiconst.TOTOP, height=200)
        headEntryContLeft = uicls.Container(parent=headEntryCont, name='headEntryContLeft', align=uiconst.TOLEFT, width=(self.leftCont.width / 2))
        headEntryContRight = uicls.Container(parent=headEntryCont, name='headEntryContRight', align=uiconst.TOLEFT, width=(self.leftCont.width / 2))
        for i in xrange(planetCommon.ECU_MAX_HEADS):
            value = self.GetResourceLayerValueForHead(i)
            if self.editsEnabled:
                state = uiconst.UI_NORMAL
            else:
                state = uiconst.UI_DISABLED
            if (i < 5):
                parent = headEntryContLeft
            else:
                parent = headEntryContRight
            btn = ExtractionHeadEntry(parent=parent, headID=i, ecuID=self.pin.id, align=uiconst.TOTOP, height=20, state=state, value=value, pin=self.pin)
            btn.OnClick = (self.OnHeadBtnClicked, i)
            self.headButtons.append(btn)

        self.currentRadius = max(min(self.pin.headRadius, planetCommon.RADIUS_DRILLAREAMAX), planetCommon.RADIUS_DRILLAREAMIN)
        sliderCont = uicls.Container(parent=self.leftCont, name='sliderCont', align=uiconst.TOBOTTOM, height=16)
        planet.ui.CaptionLabel(parent=self.leftCont, text=mls.UI_PI_EXTRACTIONAREASIZE, align=uiconst.TOBOTTOM, padBottom=2)
        BTNSIZE = 20
        BTNFONTSIZE = 8
        sliderValue = math.sqrt(((self.currentRadius - planetCommon.RADIUS_DRILLAREAMIN) / planetCommon.RADIUS_DRILLAREADIFF))
        self.areaSlider = AreaSlider(parent=sliderCont, name='areaSlider', align=uiconst.TOPLEFT, minValue=0.0, maxValue=1.0, startVal=sliderValue, hint=mls.UI_PI_EXTRACTIONAREASIZE, endsliderfunc=self.OnAreaSliderReleased, pos=((BTNSIZE - 4),
         0,
         95,
         11))
        subtrBtn = uicls.Button(parent=sliderCont, name='subtractBtn', align=uiconst.TOPLEFT, label='-', func=self.DecreaseDrillAreaSize, alwaysLite=True, fixedwidth=BTNSIZE, fontsize=BTNFONTSIZE, left=-4, top=-3)
        subtrBtn.sr.label.left += 1
        addBtn = uicls.Button(parent=sliderCont, name='addBtn', align=uiconst.TOPRIGHT, label='+', func=self.IncreaseDrillAreaSize, alwaysLite=True, fixedwidth=BTNSIZE, fontsize=BTNFONTSIZE, top=-3)
        addBtn.sr.label.left += 1
        self.areaSlider.OnSetValue = self.OnAreaSliderMoved
        if not self.editsEnabled:
            self.areaSlider.Disable()
            subtrBtn.Disable()
            addBtn.Disable()



    def DecreaseDrillAreaSize(self, *args):
        newSliderValue = self._GetNextSliderValue(increase=False)
        self.areaSlider.SetValue(newSliderValue, updateHandle=True)
        self.SetExtractorRadius()



    def IncreaseDrillAreaSize(self, *args):
        newSliderValue = self._GetNextSliderValue(increase=True)
        self.areaSlider.SetValue(newSliderValue, updateHandle=True)
        self.SetExtractorRadius()



    def _GetNextSliderValue(self, increase = True):
        oldNumCycles = None
        sliderVal = self.areaSlider.value
        maxCount = 1000
        count = 0
        while (count < maxCount):
            count += 1
            (cycleTime, numCycles,) = self._GetCycleTimeAndNumCyclesFromSliderVal(sliderVal)
            if not oldNumCycles:
                oldNumCycles = numCycles
            if (oldNumCycles != numCycles):
                break
            if increase:
                sliderVal += 0.001
            else:
                sliderVal -= 0.001

        return sliderVal



    def _GetCycleTimeAndNumCyclesFromSliderVal(self, sliderVal):
        radius = self._GetRadiusFromSliderVal(sliderVal)
        programLength = planetCommon.GetProgramLengthFromHeadRadius(radius)
        cycleTime = planetCommon.GetCycleTimeFromProgramLength(programLength)
        numCycles = int((programLength / cycleTime))
        return (cycleTime, numCycles)



    def _GetRadiusFromSliderVal(self, sliderVal):
        return (((sliderVal ** 2) * planetCommon.RADIUS_DRILLAREADIFF) + planetCommon.RADIUS_DRILLAREAMIN)



    def OnAreaSliderReleased(self, slider):
        self.SetExtractorRadius()



    def SetExtractorRadius(self):
        radius = (((self.areaSlider.value ** 2) * planetCommon.RADIUS_DRILLAREADIFF) + planetCommon.RADIUS_DRILLAREAMIN)
        self.planetUISvc.myPinManager.SetExtractionHeadRadius(self.pin.id, radius)
        self.currentRadius = radius
        self.UpdateProgram()



    def OnAreaSliderMoved(self, slider):
        AreaSlider.OnSetValue(slider, slider)
        (cycleTime, numCycles,) = self._GetCycleTimeAndNumCyclesFromSliderVal(slider.value)
        cycleTime = int((cycleTime * HOUR))
        self.barGraph.SetXLabels((mls.UI_PI_SURVEYPROGRAMSTART, util.FmtDate((cycleTime * numCycles))))



    def _ConstructCenterContainer(self):
        self.barGraph = uicls.BarGraph(parent=self.centerCont, align=uiconst.TOPLEFT, width=(((self.default_fixedWidth - self.leftCont.width) - self.rightCont.width) - 25), height=190, barUpdateDelayMs=1, barHintFunc=self.GetBarHint)
        uthread.new(self.UpdateProgram)



    def GetBarHint(self, numBar, value, maxValue):
        accOutput = sum(self.outputVals[:numBar])
        accTime = (self.currCycleTime * numBar)
        accPerHour = ((HOUR * accOutput) / accTime)
        total = sum(self.outputVals)
        return ('%s %s<br>%s %s<br><color=gray>%s:<br>%s %s<br>%s<br>%s %s' % (mls.CYCLE,
         numBar,
         value,
         mls.UI_GENERIC_UNITS,
         mls.UI_GENERIC_ACCUMULATED,
         accOutput,
         mls.UI_GENERIC_UNITS,
         util.FmtDate(accTime),
         accPerHour,
         mls.UI_PI_PERHOUR))



    def UpdateProgram(self, replaceHeadID = None, point = None):
        if (self.currentResource is None):
            return 
        heads = self.pin.heads[:]
        if self.editsEnabled:
            if (replaceHeadID is not None):
                for each in self.pin.heads:
                    if (each[0] == replaceHeadID):
                        heads.remove(each)
                        heads.append((replaceHeadID,
                         point.phi,
                         point.theta))
                        break

            colony = self.GetColony()
            (maxValue, cycleTime, numCycles, self.overlapValues,) = colony.CreateProgram(self.currentResource, self.pin.id, self.currResourceTypeID, points=heads, headRadius=self.currentRadius)
            self.UpdateOverlapValues()
            self.planetUISvc.myPinManager.SetEcuOverlapValues(self.pin.id, self.overlapValues)
        else:
            (maxValue, cycleTime, numCycles,) = self.pin.GetProgramParameters()
        self.currCycleTime = cycleTime
        xLabels = (mls.UI_PI_SURVEYPROGRAMSTART, util.FmtDate((cycleTime * numCycles)))
        self.UpdateBarGraph(maxValue, cycleTime, numCycles, xLabels)



    def UpdateOverlapValues(self):
        for (id, headButton,) in enumerate(self.headButtons):
            headButton.SetOverlapValue(self.overlapValues.get(id, None))




    def UpdateBarGraph(self, maxValue, cycleTime, numCycles, xLabels):
        self.outputVals = self.pin.GetProgramOutputPrediction(maxValue, cycleTime, numCycles)
        totalOutput = sum(self.outputVals)
        perHourOutput = ((float(totalOutput) * HOUR) / (numCycles * cycleTime))
        currOutput = self.pin.GetProducts().values()
        if currOutput:
            currOutput = currOutput[0]
        else:
            currOutput = 0
        self.outputPerHourTxt.SetText(('<t>%s: <t><b>%s</b> %s' % (mls.UI_PI_PERHOUR,
         util.FmtAmt(perHourOutput),
         mls.UI_GENERIC_UNITS)))
        self.outputTotalTxt.SetText(('<t>%s: <t><b>%s</b> %s' % (mls.UI_GENERIC_TOTAL,
         util.FmtAmt(totalOutput),
         mls.UI_GENERIC_UNITS)))
        self.barGraph.SetValues(self.outputVals)
        self.barGraph.SetXLabels(xLabels)
        self.UpdateBarTimeIndicator()
        self.programCycleTime = cycleTime



    def UpdateBarTimeIndicator(self):
        if (self.pin.IsActive() and (not self.pin.IsInEditMode())):
            if (self.barTimeIndicatorThread is None):
                self.barTimeIndicatorThread = uthread.new(self._UpdateBarTimeIndicator)
        else:
            self.barGraph.HideTimeIndicator()
            if (self.barTimeIndicatorThread is not None):
                self.barTimeIndicatorThread.kill()
                self.barTimeIndicatorThread = None



    def _UpdateBarTimeIndicator(self):
        while (self and (not self.destroyed)):
            indicatorValue = (float((blue.os.GetTime() - self.pin.installTime)) / (self.pin.expiryTime - self.pin.installTime))
            if ((indicatorValue > 0.0) and (indicatorValue < 1.0)):
                self.barGraph.ShowTimeIndicator(indicatorValue)
            blue.pyos.synchro.Sleep(10000)




    def OnHeadEntryMouseEnter(self, headID):
        self.headButtons[headID].ShowFill()



    def OnHeadEntryMouseExit(self, headID):
        self.headButtons[headID].HideFill()



    def _ConstructRightContainer(self):
        self.resourceIconButtons = {}
        numIcons = len(self.resourceTypeIDs)
        ICONSIZE = 25
        PAD = 4
        stateParent = uicls.Container(parent=self.rightCont, align=uiconst.TOTOP, height=20, padBottom=6)
        self._SetStateInfo()
        self.stateTxt = uicls.Label(parent=stateParent, text=('<center>' + self.stateInfoText), align=uiconst.TOALL, autowidth=True, autoheight=True, fontsize=10, top=4, color=util.Color.WHITE, state=uiconst.UI_NORMAL)
        uicls.Frame(parent=stateParent, color=util.Color.GetGrayRGBA(1.0, 0.2))
        self.stateColorFill = uicls.Fill(parent=stateParent, color=self.stateColor)
        if self.editsEnabled:
            state = uiconst.UI_PICKCHILDREN
        else:
            state = uiconst.UI_DISABLED
        iconCont = uicls.Container(parent=self.rightCont, align=uiconst.TOTOP, pos=(0,
         0,
         (numIcons * (ICONSIZE + PAD)),
         ICONSIZE), state=state, padding=(0,
         PAD,
         0,
         PAD))
        resourceTypes = [ (cfg.invtypes.Get(typeID).typeName, typeID) for typeID in self.resourceTypeIDs ]
        resourceTypes.sort()
        for (i, (typeName, typeID,),) in enumerate(resourceTypes):
            ib = planet.ui.IconButton(parent=iconCont, pos=((i * (ICONSIZE + PAD)),
             0,
             ICONSIZE,
             ICONSIZE), size=ICONSIZE, typeID=typeID, ignoreSize=True)
            self.resourceIconButtons[typeID] = ib
            ib.OnClick = (self.OnResourceBtnClicked, typeID)
            ib.OnMouseEnter = (self.OnResourceBtnMouseEnter, typeID)
            ib.OnMouseExit = self.OnResourceBtnMouseExit

        self.selectedResourceTxt = planet.ui.SubTextLabel(parent=self.rightCont, text='', align=uiconst.TOTOP)
        self.SetCurrentResourceText(self.currResourceTypeID)
        self.currCycleGauge = uicls.Gauge(parent=self.rightCont, align=uiconst.TOTOP, value=0.0, color=planetCommon.PLANET_COLOR_CYCLE, label=mls.UI_PI_CURRENTCYCLE, padTop=18)
        uthread.new(self._UpdateCurrCycleGauge)
        outputTxtCont = uicls.Container(parent=self.rightCont, align=uiconst.TOBOTTOM, height=40)
        planet.ui.CaptionLabel(parent=outputTxtCont, text=mls.UI_PI_OUTPUT, align=uiconst.TOTOP)
        tabs = [-6, 70]
        self.outputPerHourTxt = planet.ui.SubTextLabel(parent=outputTxtCont, text=mls.UI_GENERIC_NONE, align=uiconst.TOTOP, tabs=tabs)
        self.outputTotalTxt = planet.ui.SubTextLabel(parent=outputTxtCont, align=uiconst.TOTOP, tabs=tabs)



    def _UpdateCurrCycleGauge(self):
        while not self.destroyed:
            (txt, cycleProportion,) = planetCommon.GetPinCycleInfo(self.pin, self.programCycleTime)
            self.currCycleGauge.SetValueInstantly(cycleProportion)
            self.currCycleGauge.SetSubText(txt)
            blue.pyos.synchro.Sleep(1000)




    def _SetStateInfo(self):
        if self.pin.IsInEditMode():
            self.stateColor = util.Color.WHITE
            self.stateInfoText = mls.UI_PI_EDITSPENDING.upper()
            flash = True
        elif self.pin.IsActive():
            self.stateColor = util.Color('GREEN').SetAlpha(0.4).GetRGBA()
            self.stateInfoText = mls.UI_PI_SURVEYPROGRAMRUNNING.upper()
            flash = False
        else:
            self.stateColor = util.Color.WHITE
            self.stateInfoText = mls.UI_INFLIGHT_IDLE.upper()
            flash = True
        self.FlashStateColor(flash)



    def FlashStateColor(self, flash):
        if (self.flashStateColorThread is not None):
            self.flashStateColorThread.kill()
        if flash:
            self.flashStateColorThread = uthread.new(self._FlashStateColor)



    def _FlashStateColor(self):
        CYCLETIME = 3.0
        t = 0.0
        while not self.destroyed:
            if self.stateColor:
                t += ((1.0 / blue.os.fps) % CYCLETIME)
                x = ((math.sin((((2 * math.pi) * t) / CYCLETIME)) * 0.2) + 0.3)
                color = util.Color(*self.stateColor).SetAlpha(x)
                self.stateColorFill.color.SetRGB(*color.GetRGBA())
            blue.pyos.synchro.Yield()




    def _ConstructBottomContainer(self):
        if self.editsEnabled:
            btnName = mls.UI_PI_INSTALLPROGRAM
            btns = [(btnName,
              self._ApplyProgram,
              None)]
        else:
            btnName = mls.UI_PI_SURVEYSTOPPROGRAM
            btns = [(btnName,
              self._StopProgram,
              None)]
        btns.append((mls.UI_CMD_CLOSE,
         self._Cancel,
         None))
        btnGroup = uix.MakeBtnGroup(btns=btns, where=self.bottomCont, line=True)
        self.submitButton = uiutil.FindChild(btnGroup, ('%s_Btn' % btnName))
        self.SetCurrentResource(self.currResourceTypeID)
        self._SetSubmitButtonState()



    def _SetSubmitButtonState(self):
        nextEditTime = self.pin.GetNextEditTime()
        if ((nextEditTime is not None) and ((nextEditTime > blue.os.GetTime()) and (not self.pin.IsInEditMode()))):
            self.submitButton.Disable()
            uthread.new(self._UnlockStopButtonThread).context = '_SetSubmitButtonState'
        elif (self.currentResource is None):
            self.submitButton.Disable()
            self.submitButton.SetHint('')
        else:
            self.submitButton.Enable()
            self.submitButton.SetHint('')



    def _UnlockStopButtonThread(self):
        nextEditTime = self.pin.GetNextEditTime()
        while (nextEditTime > blue.os.GetTime()):
            self.submitButton.SetHint((mls.UI_PI_NEXTEDITAVAILABLE % {'time': util.FmtDate((nextEditTime - blue.os.GetTime()))}))
            blue.pyos.synchro.Sleep(200)
            if ((not self) or self.destroyed):
                return 

        self._SetSubmitButtonState()



    def OnHeadBtnClicked(self, headID, btn):
        head = self.pin.FindHead(headID)
        if not head:
            self.PlaceProbeAtDefaultPosition(headID)
        else:
            self.planetUISvc.myPinManager.RemoveExtractionHead(self.pin.id, headID)
            if (headID in self.extractionHeadValues):
                self.extractionHeadValues.pop(headID)
            self.headButtons[headID].SetValue(None)
        self.UpdateProgram()



    def OnBeginDragExtractionHead(self, headID, surfacePoint):
        sm.GetService('audio').SendUIEvent('wise:/msg_pi_extractor_play')
        sm.GetService('audio').SendUIEvent('wise:/msg_pi_extractor_distorted_play')
        if (self.currResourceTypeID is not None):
            self.dragThread = uthread.new(self._WhileExtractionHeadDraggedThread, headID, surfacePoint)
        else:
            self.headButtons[headID].SetValue(0.0)



    def OnEndDragExtractionHead(self):
        sm.GetService('audio').SendUIEvent('wise:/msg_pi_extractor_stop')
        sm.GetService('audio').SendUIEvent('wise:/msg_pi_extractor_distorted_stop')
        if (self.dragThread is not None):
            self.dragThread.kill()
            self.dragThread = None



    def OnExtractionHeadMoved(self, headID, surfacePoint):
        self.UpdateHeadPosition(headID, surfacePoint)



    def _WhileExtractionHeadDraggedThread(self, headID, surfacePoint):
        while not self.destroyed:
            if (self.currentResource is not None):
                self.UpdateProgram(replaceHeadID=headID, point=surfacePoint)
            blue.pyos.synchro.Sleep(200)




    def UpdateHeadPosition(self, headID, surfacePoint):
        heads = self.pin.heads
        headRadius = self.pin.headRadius
        if (self.currentResource is not None):
            value = self.GetResourceLayerValueForHead(headID, surfacePoint)
            overlapValue = self.overlapValues.get(headID, None)
            self.headButtons[headID].SetValue(value=value, overlapValue=overlapValue)
            if (value is not None):
                sm.GetService('audio').SetGlobalRTPC('pitch_extractor_quality', ((100 * value) / 250))
            if (overlapValue is not None):
                sm.GetService('audio').SetGlobalRTPC('volume_extractor_interference', (10 * overlapValue))
        else:
            self.headButtons[headID].SetValue(value=0.0)



    def UpdateHeadButtonValues(self):
        for headButton in self.headButtons:
            value = self.GetResourceLayerValueForHead(headButton.headID)
            self.extractionHeadValues[headButton.headID] = value
            headButton.SetValue(value)




    def GetResourceLayerValueForHead(self, headID, surfacePoint = None):
        if self.currResourceTypeID:
            head = self.pin.FindHead(headID)
            if head:
                (headID, phi, theta,) = head
                if surfacePoint:
                    theta = surfacePoint.theta
                    phi = surfacePoint.phi
                return max(0.0, builder.GetValueAt(self.sh, theta, phi))
        else:
            if (self.pin.FindHead(headID) is not None):
                return 0.0
            else:
                return 



    def PlaceProbeAtDefaultPosition(self, headID):
        OFFSET = 0.08
        VEC_X = (-1, 0, 0)
        rotAngle = (((float(headID) / planetCommon.ECU_MAX_HEADS) * 2) * math.pi)
        ecuVector = self.planetUISvc.myPinManager.pinsByID[self.pin.id].surfacePoint.GetAsXYZTuple()
        normal = geo2.Vec3Cross(ecuVector, VEC_X)
        normal = (geo2.Vector(*normal) * OFFSET)
        posVec = geo2.Vec3Subtract(ecuVector, normal)
        posVec = geo2.Vec3Normalize(posVec)
        rotMat = geo2.MatrixRotationAxis(ecuVector, rotAngle)
        posVec = geo2.Multiply(rotMat, posVec)
        surfacePoint = planet.SurfacePoint(*posVec)
        self.planetUISvc.myPinManager.PlaceExtractionHead(self.pin.id, headID, surfacePoint, self.currentRadius)
        self.UpdateHeadPosition(headID, surfacePoint)



    def _ApplyProgram(self, *args):
        if (self.currResourceTypeID is not None):
            self.planet.InstallProgram(self.pin.id, self.currResourceTypeID, self.currentRadius)
        self.planetUISvc.myPinManager.ReRenderPin(self.pin)
        self.SelfDestruct()



    def _Cancel(self, *args):
        self.planetUISvc.CancelInstallProgram(self.pin.id, self.pinData)
        self.SelfDestruct()



    def _StopProgram(self, *args):
        self.editsEnabled = True
        self.pin.inEditMode = True
        self.leftCont.Flush()
        self.rightCont.Flush()
        self.bottomCont.Flush()
        self.planetUISvc.myPinManager.UnlockHeads(self.pin.id)
        self.planetUISvc.GetCurrentPlanet().InstallProgram(self.pin.id, None, self.currentRadius)
        self._ConstructLeftContainer()
        self._ConstructRightContainer()
        self._ConstructBottomContainer()



    def OnResourceBtnClicked(self, typeID, btn, *args):
        self.SetCurrentResource(typeID)



    def OnResourceBtnMouseEnter(self, typeID, btn, *args):
        self.SetCurrentResourceText(typeID)
        planet.ui.IconButton.OnMouseEnter(btn)



    def OnResourceBtnMouseExit(self, btn, *args):
        self.SetCurrentResourceText(self.currResourceTypeID)
        planet.ui.IconButton.OnMouseExit(btn)



    def SetCurrentResource(self, typeID = None):
        self.currResourceTypeID = typeID
        self.currentResource = (None if (typeID is None) else self.planet.GetResourceHarmonic(typeID))
        for (ibTypeID, ib,) in self.resourceIconButtons.iteritems():
            ib.SetSelected(False)
            if ((not self.editsEnabled) and (ibTypeID != typeID)):
                ib.Disable()

        if typeID:
            self.resourceIconButtons[typeID].SetSelected(True)
        self._SetSubmitButtonState()
        if (typeID is None):
            self.sh = None
        else:
            (inRange, self.sh,) = self.planetUISvc.planet.GetResourceData(self.currResourceTypeID)
        self.SetCurrentResourceText(typeID)
        self.UpdateHeadButtonValues()
        self.UpdateProgram()
        self.planetUISvc.ShowResource(typeID)



    def SetCurrentResourceText(self, typeID):
        if typeID:
            text = cfg.invtypes.Get(typeID).name
        else:
            text = mls.UI_PI_NORESOURCESELECTED
        self.selectedResourceTxt.text = text



    def OnPlanetViewChanged(self, newPlanet, oldPlanet):
        self.SelfDestruct()



    def OnEditModeBuiltOrDestroyed(self):
        if ((not self) or self.destroyed):
            return 
        if (self.planet.GetPin(self.pin.id) is None):
            self.SelfDestruct()



    def OnEditModeChanged(self, isEdit):
        if ((not self) or self.destroyed):
            return 
        if not isEdit:
            self.SelfDestruct()



    def _CloseClick(self, *args):
        self.planetUISvc.CancelInstallProgram(self.pin.id, self.pinData)
        uicls.Window._CloseClick(self, *args)



    def OnClose_(self, *args):
        if hasattr(self, 'revertToResource'):
            self.planetUISvc.ShowResource(self.revertToResource)
        self.planetUISvc.ExitSurveyMode()
        self.planetUISvc.eventManager.SetStateNormal()



    def GetColony(self):
        return self.planetUISvc.GetCurrentPlanet().GetColony(session.charid)




class ExtractionHeadEntry(uicls.Container):
    __guid__ = 'uicls.ExtractionHeadEntry'
    default_name = 'ExtractionHeadEntry'
    default_height = 20
    default_state = uiconst.UI_NORMAL
    default_padBottom = 9

    def ApplyAttributes(self, attributes):
        uicls.Container.ApplyAttributes(self, attributes)
        self.headID = attributes.headID
        self.ecuID = attributes.ecuID
        self.value = attributes.get('value', None)
        self.pin = attributes.pin
        self.overlapValue = None
        self.fill = uicls.Fill(parent=self, align=uiconst.TOTOP, height=self.default_height, color=util.Color(*util.Color.WHITE).SetAlpha(0.1).GetRGBA(), state=uiconst.UI_HIDDEN, idx=0)
        self.icon = uicls.Icon(parent=self, icon='ui_77_32_38', size=self.default_height, ignoreSize=True, state=uiconst.UI_DISABLED, left=-2)
        self.label = planet.ui.SubTextLabel(parent=self, text='', left=self.default_height, top=4, fontsize=10)
        self.SetValue(self.value)



    def SetValue(self, value = None, overlapValue = None):
        self.value = value
        self.overlapValue = overlapValue
        if (value is None):
            txt = '-'
            self.opacity = 0.5
        elif overlapValue:
            txt = ('%.2f<br><fontsize=9><color=red>(-%.1f%%)' % (value, (100 * overlapValue)))
        else:
            txt = ('%.2f' % value)
        self.opacity = 1.0
        self.label.text = txt



    def GetHint(self, *args):
        if (self.value is None):
            return ('%s<br><color=gray>%s: +%s %s<br>%s: +%s %s' % (mls.UI_PI_INSTALLNEWEXTRACTORHEAD,
             mls.UI_GENERIC_POWER,
             self.pin.GetExtractorHeadPowerUsage(),
             mls.UI_GENERIC_MEGAWATTSHORT,
             mls.UI_GENERIC_CPU,
             self.pin.GetExtractorHeadCpuUsage(),
             mls.UI_GENERIC_TERAFLOPSSHORT))
        else:
            hint = (mls.UI_PI_EXTRACTORHEADQUALITYINDEX % {'headID': (self.headID + 1),
             'value': self.value})
            if self.overlapValue:
                hint += ('<br><br>' + (mls.UI_PI_SURVEYDISTURBANCEHINT % {'disturbanceVal': (100 * self.overlapValue)}))
            return hint



    def SetOverlapValue(self, overlapValue):
        self.SetValue(self.value, overlapValue)



    def OnMouseEnter(self, *args):
        if ((not self) or self.destroyed):
            return 
        self.ShowFill()
        if (self.value is None):
            self.label.text = mls.UI_CMD_INSTALL.upper()
            self.opacity = 1.0
        sm.GetService('planetUI').myPinManager.OnExtractionHeadMouseEnter(self.ecuID, self.headID)



    def OnMouseExit(self, *args):
        if ((not self) or self.destroyed):
            return 
        self.HideFill()
        if (self.value is None):
            self.label.text = '-'
            self.opacity = 0.5
        sm.GetService('planetUI').myPinManager.OnExtractionHeadMouseExit(self.ecuID, self.headID)



    def ShowFill(self):
        if self.overlapValue:
            self.fill.height = 28
        else:
            self.fill.height = self.default_height
        self.fill.state = uiconst.UI_DISABLED



    def HideFill(self):
        self.fill.state = uiconst.UI_HIDDEN




class AreaSlider(uicls.Slider):
    __guid__ = 'uicls.AreaSlider'

    def ApplyAttributes(self, attributes):
        bgCont = uicls.Container(parent=self, name='bgCont', align=uiconst.TOALL, padLeft=2)
        self.sliderFill = uicls.Fill(parent=bgCont, align=uiconst.TOLEFT, pos=(0, 0, 0, 0), color=util.Color.GetGrayRGBA(1.0, 0.5))
        uicls.Slider.ApplyAttributes(self, attributes)



    def Prepare_Handle_(self):
        self.handle = uicls.Line(name='handle', parent=self, align=uiconst.BOTTOMLEFT, state=uiconst.UI_NORMAL, pos=(0,
         -1,
         4,
         (self.height + 2)), color=util.Color.WHITE)
        self.handle.OnMouseDown = self.OnHandleMouseDown
        self.handle.OnMouseUp = self.OnHandleMouseUp
        self.handle.OnMouseMove = self.OnHandleMouseMove



    def OnSetValue(self, *args):
        self.sliderFill.width = self.handle.left



    def Prepare_Underlay_(self):
        self.frame = uicls.Frame(parent=self, align=uiconst.TOBOTTOM, pos=(0,
         0,
         0,
         self.height), color=(1.0, 1.0, 1.0, 0.3), state=uiconst.UI_NORMAL)
        self.frame.OnClick = self.OnFrameClicked



    def Disable(self, *args):
        uicls.Slider.Disable(self, args)
        self.handle.state = uiconst.UI_HIDDEN



    def Enable(self, *args):
        uicls.Slider.Enable(self, args)
        self.handle.state = uiconst.UI_NORMAL




